#include <iostream>
#include <ostream>
#include <type_traits>

template <typename T,
         typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void TestFunc(T msg) {
    std::cout << "is integral" << std::endl;
}

template <typename T,
         typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
void TestFunc(T msg) {
    std::cout << "is not integral" << std::endl;
}

template <typename T,
         typename std::enable_if<std::__is_char<T>::value, int>::type = 0>
void TestFunc(T msg) {
    std::cout << "is char" << std::endl;
}

template <typename T,
         typename std::enable_if<std::__is_unsigned_integer<T>::value, int>::type = 0>
void TestFunc(T msg) {
    std::cout << "is unsigned_integer" << std::endl;
}

template<typename T>
typename std::enable_if<std::is_same<T, char>::value, T>::type
inline foo(T t) {
    return t;
}
template<typename T>
typename std::enable_if<std::is_same<T, unsigned char>::value, T>::type
inline foo(T t) {
    return t;
}
template<typename T>
typename std::enable_if<std::is_same<T, int>::value, T>::type
foo(T t) {
    return t * 2;
}
